package service_user

import (
	"errors"
	"github.com/golang-jwt/jwt"
	"strings"
	"time"
	"tools-api/src/common/def"
	"tools-api/src/jcj/model"
)

// 获取密钥 0:RefreshToken 1:AccessToken
func getSecret(_type int) []byte {
	return []byte(def.Config.GetStringSlice("app.jcj.token.secret")[_type])
}

// 获取过期时间点
func getDayEnd() int64 {
	expireDay := def.Config.GetIntSlice("app.jcj.token.expire")[0]
	if expireDay == 0 {
		expireDay = 31
	}
	currentTime := time.Now()
	// 为避免在使用app过程中实效退出，计算时间在过期天数的23点59分59秒
	endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location()).
		AddDate(0, 0, expireDay)

	return endTime.Unix()
}

// RefreshTokenGenerate 生成 RefreshToken
func RefreshTokenGenerate(uuid string, tokenVersion int) (string, error) {
	claims := jwt.MapClaims{
		"uuid":    uuid,
		"version": tokenVersion,
		"exp":     getDayEnd(),
		"iat":     time.Now().Unix(),
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	return token.SignedString(getSecret(0)) // 生成密钥用最后一个
}

// AccessTokenGenerate 生成AccessToken
func AccessTokenGenerate(uuid string, tokenVersion int) (string, error) {
	// 生成新的 AccessToken（有效期短）
	expireSecond := def.Config.GetIntSlice("app.jcj.token.expire")[1]
	accessClaims := jwt.MapClaims{
		"uuid":    uuid,
		"version": tokenVersion,
		"exp":     time.Now().Add(time.Duration(expireSecond) * time.Second).Unix(), // 有效期
		"iat":     time.Now().Unix(),
	}

	accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
	return accessToken.SignedString(getSecret(1))
}

// AccessTokenExchange 使用 RefreshToken 换取新的 AccessToken
func AccessTokenExchange(refreshToken string, deviceType, deviceId string) (string, error) {
	refreshToken = strings.TrimSpace(refreshToken)
	if len(refreshToken) == 0 {
		return "", errors.New("invalid refresh token")
	}
	// 验证 Refresh Token
	token, err := jwt.Parse(refreshToken, func(token *jwt.Token) (interface{}, error) {
		return getSecret(0), nil
	})

	if err != nil {
		return "", err
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok || !token.Valid {
		return "", errors.New("invalid refresh token")
	}

	// 提取用户信息
	version := int(claims["version"].(float64))
	uuid := claims["uuid"].(string)
	tokenVersion := model.UserLoginRecord{}.GetTokenVersion(uuid, deviceType, deviceId)
	if version != tokenVersion {
		return "", errors.New("invalid refresh token")
	}
	return AccessTokenGenerate(uuid, version)
}

// AccessTokenVerify 校验
func AccessTokenVerify(accessToken, deviceType, deviceId string) (string, error) {
	accessToken = strings.TrimSpace(accessToken)
	if len(accessToken) == 0 {
		return "", errors.New("invalid access token")
	}
	token, err := jwt.Parse(accessToken, func(token *jwt.Token) (interface{}, error) {
		return getSecret(1), nil
	})

	if err != nil {
		return "", err
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok || !token.Valid {
		return "", errors.New("invalid access token")
	}
	// 提取用户信息
	version := int(claims["version"].(float64))
	uuid := claims["uuid"].(string)
	tokenVersion := model.UserLoginRecord{}.GetTokenVersion(uuid, deviceType, deviceId)
	if version != tokenVersion {
		return "", errors.New("invalid access token")
	}
	return uuid, nil
}
